package dk.viauc.cmclang.intlang;

import dk.viauc.cmclang.intlang.ast.*;

import java.awt.*;
import javax.swing.*;
import javax.swing.tree.*;

public class ASTViewer extends JFrame {

	private static final Font NODE_FONT = new Font("Verdana", Font.PLAIN, 24);

	public ASTViewer(AST ast) {
		super("Abstract Syntax Tree");

		DefaultMutableTreeNode root = createTree(ast);
		JTree tree = new JTree(root);
		DefaultTreeCellRenderer renderer = new DefaultTreeCellRenderer();
		renderer.setFont(NODE_FONT);
		tree.setCellRenderer(renderer);

		add(new JScrollPane(tree));

		setSize(1024, 768);
		setVisible(true);

		setDefaultCloseOperation(EXIT_ON_CLOSE);
	}

	private DefaultMutableTreeNode createTree(AST ast) {
		DefaultMutableTreeNode node = new DefaultMutableTreeNode(
				"*** WHAT??? ***");

		if (ast == null)
			node.setUserObject("*** NULL ***");
		else if (ast instanceof Program) {
			node.setUserObject("Program");
			node.add(createTree(((Program) ast).block));
		} else if (ast instanceof Block) {
			node.setUserObject("Block");
			// node.add( createTree( ((Block)ast).functions ) );
			for (FunctionDeclaration f : ((Block) ast).functions)
				node.add(createTree(f));
		} else if (ast instanceof FunctionDeclaration) {
			node.setUserObject("FunctionDeclaration");
			node.add(createTree(((FunctionDeclaration) ast).ident));
			node.add(createTree(((FunctionDeclaration) ast).type));
			node.add(createTree(((FunctionDeclaration) ast).params));
			node.add(createTree(((FunctionDeclaration) ast).statements));
		} else if (ast instanceof Identifier) {
			node.setUserObject("Identifier " + ((Identifier) ast).spelling);
		} else if (ast instanceof dk.viauc.cmclang.intlang.ast.Type) {
			node.setUserObject("Type "
					+ ((dk.viauc.cmclang.intlang.ast.Type) ast).type);
		} else if (ast instanceof DeclarationList) {
			node.setUserObject("DeclarationsList");

			for (Declaration d : ((DeclarationList) ast).dec)
				node.add(createTree(d));
		} else if (ast instanceof VariableDeclaration) {
			node.setUserObject("VariableDeclaration");
			node.add(createTree(((VariableDeclaration) ast).id));
			node.add(createTree(((VariableDeclaration) ast).type));
			node.add(createTree(((VariableDeclaration) ast).term));
			if (ast instanceof VarArrayDeclaration) {
				node.setUserObject("VarArrayDeclaration");
				node.add(createTree(((VarArrayDeclaration) ast).size));
			//	ExpList eList=;
				node.add(createTree((((VarArrayDeclaration) ast).values)));
			}
		} else if (ast instanceof FunctionDeclaration) {
			node.setUserObject("FunctionDeclaration");
			node.add(createTree(((FunctionDeclaration) ast).ident));
			node.add(createTree(((FunctionDeclaration) ast).type));
			node.add(createTree(((FunctionDeclaration) ast).params));
			node.add(createTree(((FunctionDeclaration) ast).statements));
		} else if (ast instanceof VarArrayDeclaration) {
				// moved to VaraibleDeclaration - VarArrayDec is the subclass
		} else if (ast instanceof StatementList) {
			node.setUserObject("StatementList");

			for (Statement s : ((StatementList) ast).statements)
				node.add(createTree(s));
		} else if (ast instanceof ExpressionStatement) {
			node.setUserObject("ExpressionStatement");
			node.add(createTree(((ExpressionStatement) ast).exp));
		} else if (ast instanceof IfStatement) {
			node.setUserObject("IfStatement");
			node.add(createTree(((IfStatement) ast).exp));
			node.add(createTree(((IfStatement) ast).doPart));
			node.add(createTree(((IfStatement) ast).elsePart));
		} else if (ast instanceof WhileStatement) {
			node.setUserObject("WhileStatement");
			node.add(createTree(((WhileStatement) ast).exp));
			node.add(createTree(((WhileStatement) ast).stats));
		} else if (ast instanceof WriteStatament) {
			node.setUserObject("WriteStatament");
			node.add(createTree(((WriteStatament) ast).exp));
		} else if (ast instanceof ReadStatement) {
			node.setUserObject("ReadStatement");
			node.add(createTree(((ReadStatement) ast).exp));
		} else if (ast instanceof DecsStatement) {
			node.setUserObject("DecsStatement");
			node.add(createTree(((DecsStatement) ast).stlist));
		} else if (ast instanceof ReturnStatement) {
			node.setUserObject("ReturnStatement");
			node.add(createTree(((ReturnStatement) ast).retExpresssion));
		} else if (ast instanceof BinaryExpression) {
			node.setUserObject("BinaryExpression");
			node.add(createTree(((BinaryExpression) ast).operator));
			node.add(createTree(((BinaryExpression) ast).operand1));
			node.add(createTree(((BinaryExpression) ast).operand2));
		} else if (ast instanceof CallExpression) {
			node.setUserObject("CallExpression");
			node.add(createTree(((CallExpression) ast).name));
			node.add(createTree(((CallExpression) ast).explist));
		} else if (ast instanceof IntLitExpression) {
			node.setUserObject("IntLitExpression");
			node.add(createTree(((IntLitExpression) ast).literal));
		} else if (ast instanceof BoolLitExpression) {
			node.setUserObject("BoolLitExpression");
			node.add(createTree(((BoolLitExpression) ast).bool));
		} else if (ast instanceof VarExpression) {
			node.setUserObject("VarExpression");
			node.add(createTree(((VarExpression) ast).id));
		} else if (ast instanceof FuncCallExpression) {
			node.setUserObject("FuncCallExpression");
			node.add(createTree(((FuncCallExpression) ast).id));
		} else if (ast instanceof ArrayGetExpression) {
			node.setUserObject("ArrayGetExpression");
			node.add(createTree(((ArrayGetExpression) ast).id));
			node.add(createTree(((ArrayGetExpression) ast).il));
		} else if (ast instanceof ExpList) {
			node.setUserObject("ExpList");

			for (Expression e : ((ExpList) ast).exp)
				node.add(createTree(e));
		} else if (ast instanceof Identifier) {
			node.setUserObject("Identifier " + ((Identifier) ast).spelling);
		} else if (ast instanceof IntegerLiteral) {
			node.setUserObject("IntegerLiteral "
					+ ((IntegerLiteral) ast).spelling);
		} else if (ast instanceof IntLiteralList) {
			node.setUserObject("IntLiteralList");

			for (IntegerLiteral i : ((IntLiteralList) ast).intlist)
				node.add(createTree(i));
		} else if (ast instanceof BoolLiteral) {
			node.setUserObject("BoolLiteral " + ((BoolLiteral) ast).spelling);
		} else if (ast instanceof Operator) {
			node.setUserObject("Operator " + ((Operator) ast).spelling);
		} else if (ast instanceof AddOper) {
			node.setUserObject("AddOper " + ((AddOper) ast).spelling);
		} else if (ast instanceof ArrayOper) {
			node.setUserObject("ArrayOper " + ((ArrayOper) ast).spelling);
		} else if (ast instanceof AssOper) {
			node.setUserObject("AssOper " + ((AssOper) ast).spelling);
		} else if (ast instanceof BoolOper) {
			node.setUserObject("BoolOper " + ((BoolOper) ast).spelling);
		} else if (ast instanceof MulOperator) {
			node.setUserObject("MulOperator " + ((MulOperator) ast).spelling);
		}
		return node;
	}

}
